<?php

namespace App\Controllers\Order;

use App\Models\Order\Order;
use \App\Libs\Pay\PayLibs;
use App\Libs\Helper\WeixinHelper;
use App\Models\User\User;
use App\Libs\DB\PailePdo;
use App\Models\Order\PailebaoOrder;
class AgreeUserRefund extends \App\Libs\Base\BaseAction
{


    protected $orderModel;
    protected $refundData;
    protected function beforeRun()
    {
        parent::beforeRun();
//        $this->needLogin = TRUE;
    }
    //退款接口，
    //负责修改订单状态等，干一些杂事;
    //退款状态码：以50000为基础
    public function execute()
    {
        if (!$this->request->has('order_sn')) {
            return \App\Libs\Views\Json::view(1, '缺少订单号', []);
        }
        $order_sn = $this->request->get('order_sn');
        $matchOrder = Order::find([
            'conditions' => 'order_sn=?1',
            'bind' => [1 => $order_sn]
        ]);
        //检查订单状态，只有是1，已支付的，才能退款，其他状态不能退款；
        if ($matchOrder->status != '7') {
            return \App\Libs\Views\Json::view(1, '退款失败：退款失败，订单未申请退款；', []);
        }
        $this->orderModel = $matchOrder;
        //接下来去调用各自的方法，去直接处理退款；
        switch ($matchOrder->pay_method) {
            case '1'://微信退款；
                //var_dump(APP_PATH . '/app/configs'.DIRECTORY_SEPARATOR.'Cert'.DIRECTORY_SEPARATOR.'apiclient_cert.pem');die;
                $validateRes = $this->weixinRefund();//返回的是原始数据数据，或者是false，验签失败；
                if ($validateRes != false) {
                    if(isset($validateRes['err_code_des'])){
                        return \App\Libs\Views\Json::view(1, '退款失败，请重试!', $validateRes);
                    }
                    $changeRes = $this->changeOrderStatus();
                    if ($changeRes == true) {
                        return \App\Libs\Views\Json::view(0, '退款成功', []);
                    } else {
                        return \App\Libs\Views\Json::view(1, '退款失败，请重试!', []);
                    }

                } else {
                    return \App\Libs\Views\Json::view(1, '退款失败，请重试!', []);
                }
                break;
            case '2'://支付宝
                $res = $this->alipayRefund();
                if (is_array($res)) {
                    return \App\Libs\Views\Json::view(1, '退款失败', $res);
                } else {
                    return \App\Libs\Views\Json::view(0, '退款成功', []);
                }
                break;
            case '3'://派乐宝退款;
              $res =  $this->pailebaoRefund();
              if($res){
                  return \App\Libs\Views\Json::view(0, '派乐宝余额退款成功', []);
              }else{
                  return \App\Libs\Views\Json::view(1, '退款失败', $res);
              }
                break;
        }
    }

    public function weixinRefund()
    {
        //交易时间超过一年的订单无法提交退款
        //支付部分退款；
        $params = array(
            'appid' => WeixinHelper::$appID,
            'mch_id' => WeixinHelper::$mchID,
            'nonce_str' => WeixinHelper::getGenerate(mt_rand(20, 32)),
            'out_trade_no' => $this->orderModel->order_sn,
            'out_refund_no' => $this->orderModel->order_sn,
            //订单金额;
            'total_fee' => $this->orderModel->price*100,      //
            'refund_fee' => $this->orderModel->price*100,  //
        );
        ksort($params);
        $str = urldecode(http_build_query($params));
        $str .= '&key=' . WeixinHelper::$key;
        $params['sign'] = strtoupper(md5($str));
        $xmlParams = WeixinHelper::arrayToXml($params);
        $data = self::weixinRefundPostCert($xmlParams);
        $this->refundData = $data;//保存退款数据以便存起来；
        if (!$data) {
            return \App\Libs\Views\Json::view(1, '失败，请重试', []);
        }
        $sourceData = WeixinHelper::xmlToArray($data);
        $res = self::validate($sourceData);
        return $res;
    }

    public function alipayRefund()
    {
        $refundInfo = [
            'out_trade_no' => $this->orderModel->order_sn,       //本系统的订单号
            'refund_amount' => $this->orderModel->price,  //退款金额
        ];

        $alipay = new PayLibs(1);
        $response = $alipay->alipayRefund($refundInfo);
        $this->refundData = $response;
        /*
        stdClass Object
        (
            [code] => 10000
            [msg] => Success
            [buyer_logon_id] => 150****4593
            [buyer_user_id] => 2088402458630484
            [fund_change] => Y
            [gmt_refund_pay] => 2017-09-23 14:07:41
            [out_trade_no] => 112017092314050501424
            [refund_fee] => 0.01
            [send_back_fee] => 0.00
            [trade_no] => 2017092321001004480258848549
        )*/
        if ($response->code == '10000' && $response->msg == 'Success' && $response->refund_fee == $this->orderModel->price) {
            $this->changeOrderStatus(); //更改订单状态；
            return true;
        } else {
            return ['result' => false, 'response' => $response];
        }
    }

    public function pailebaoRefund(){
//        $orderModel
        //更改订单状态，加钱；

        PailePdo::begin();
        $this->orderModel->status = 6;
        if($this->orderModel->update()){
            $matchUser = User::find($this->orderModel->uid);
            $matchUser->balance = (float)$matchUser->balance + (float)$this->orderModel->price;
            if($matchUser->update()){
                //添加退款流水流水；
                $newPaileOrder = new PailebaoOrder();
                $newPaileOrder->uid = $this->orderModel->uid;
                $newPaileOrder->order_sn = $this->orderModel->order_sn;
                $newPaileOrder->operate = 1; //tinyint:1:充值，0：消费
                $newPaileOrder->money_num = $this->orderModel->price;
                //0:待支付，1，已经支付，
                $newPaileOrder->order_status = 1;
                $refundInfo=[
                    'type' => '购物订单退款',
                    'buy_order_sn' => $this->orderModel->order_sn,
        	   'refund_amount' => $this->orderModel->price   
		  ];
                $newPaileOrder->operate_info = json_encode($refundInfo);
                if (!$newPaileOrder->create()) {
                    PailePdo::rollback();
                    return \App\Libs\Views\Json::view(0, '失败：系统繁忙,请稍后.', ['subcode' => 44444, 'submsg' => '失败：系统繁忙,请稍后.']);
                }

                PailePdo::commit();
                return true;
            }else{
                PailePdo::rollback();
                return false;
            }
        }else{
            PailePdo::rollback();
            return false;
        }
    }


    public function changeOrderStatus()
    {
        $this->orderModel->status = 6;
        $this->orderModel->refund_info = json_encode($this->refundData);
        if ($this->orderModel->update()) {
            return true;
        } else {
            return false;
        }
    }

    //使用证书调用接口；
    public static function weixinRefundPostCert($xmlparams)
    {
        $url = 'https://api.mch.weixin.qq.com/secapi/pay/refund';
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_HEADER, 0);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 1);//证书检查
        curl_setopt($ch, CURLOPT_SSLCERTTYPE, 'pem');
        curl_setopt($ch, CURLOPT_SSLCERT,APP_PATH . '/app/configs'.DIRECTORY_SEPARATOR.'Cert'.DIRECTORY_SEPARATOR.'apiclient_cert.pem');
        curl_setopt($ch, CURLOPT_SSLCERTTYPE, 'pem');
        curl_setopt($ch, CURLOPT_SSLKEY,APP_PATH . '/app/configs'.DIRECTORY_SEPARATOR.'Cert'.DIRECTORY_SEPARATOR. 'apiclient_key.pem');
        curl_setopt($ch, CURLOPT_SSLCERTTYPE, 'pem');
        curl_setopt($ch, CURLOPT_CAINFO,APP_PATH . '/app/configs'.DIRECTORY_SEPARATOR.'Cert'.DIRECTORY_SEPARATOR. 'rootca.pem');
        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $xmlparams);

        $data = curl_exec($ch);
        if ($data) { //返回来的是xml格式需要转换成数组再提取值，用来做更新
            return $data;
        } else {
            return false;
        }
    }
    //验签；
    public static function validate($sourceData)
    {
        $sign = $sourceData['sign'];
        unset($sourceData['sign']);
        //去除空元素；
        foreach ($sourceData as $key => $val) {
            if (empty($sourceData[$key])) {
                unset($sourceData[$key]);
            }
        }
        ksort($sourceData);
        $str = http_build_query($sourceData);
        $str .= '&key=' . \App\Libs\Helper\WeixinHelper::$key;
        $md5 = strtoupper(md5($str));
        if ($sign !== $md5) {
            return $sourceData;
        } else {
            return false;
        }
    }

}
